#include "Radius3DHandler.h"
#include "CmdManager.h"
#include "Operation/OpReplace.h"
#include "SelectHandler3D.h"
#include "SendPointHandlerBase.h"
#include "Ucs.h"
#include "Scene.h"
#include "PointHandler.h"
#include "QtOSGWidget.h"

Radius3DHandler::Radius3DHandler()
{
}

Radius3DHandler::~Radius3DHandler()
{
}

void Radius3DHandler::input(const QVariant& data, const QString& rawInput, CommandSource cs)
{
	auto scene = getScene();
	auto widget3D = getWidget();
	auto sph = getSendPointHandler();
	auto selector = qobject_cast<SelectHandler3D*>(getSelectHandler());
	if (data.type() == QVariant::Bool)
	{
		bool esc = !data.toBool();
		if (esc)
		{
			selector->clearSelection();
			clearInput();
			if (m_arc)
			{
				auto parent = m_arc->getParent();
				widget3D->pauseRenderThread();
				parent->removeChild(m_arc);
				widget3D->resumeRenderThread();
			}
			emit finished();
			return;
		}
	}

	if (status() == 0)
	{
		m_pointStateMachine = std::make_shared<PointHandler>();
		m_pointStateMachine->setCmdManager(cmdManager());
		if (selector)
		{
			selector->clearSelection();
			selector->beginSelect(D3CurveMask,1);
			prompt(1, tr("选择对象: "));
		}
		else
		{
			emit finished();
		}
		return;
	}
	
	if (status() == 1)
	{
		if (selector && selector->done())
		{
			auto selections = selector->selectionSet();
			if (selections.size() > 0)
			{
				auto selection = *selections.begin();
				std::shared_ptr<Ent> ent = std::dynamic_pointer_cast<Ent>(selection);
				m_originArc = std::dynamic_pointer_cast<Arc3D>(ent);
				if (m_originArc)
				{
					auto parent = ent->getParent();
					m_arc = std::static_pointer_cast<Arc3D>(m_originArc->clone());
					widget3D->pauseRenderThread();
					parent->addChild(m_arc);
					widget3D->resumeRenderThread();
					if (sph)
					{
						sph->setPointMask(CS_LBTNDOWN | CS_MOUSEMOVE);
					}
					m_matrix = m_arc->getMatrix();
					show3DRubberLine(true);
					set3DRubberLineP1(m_arc->center()*m_matrix);
					enableMouseHandler(MouseHandlerID::PointSender);
					m_pointStateMachine->setPrompt0(tr("指定圆或圆弧半径"));
					setStatus(2);
					m_pointStateMachine->reset();
				}
				else
				{
					selector->clearSelection();
					selector->beginSelect(D3CurveMask, 1);
					remark(tr("请选择圆或圆弧"));
				}
			}
		}
		return;
	}

	if (status() == 2)
	{
		m_pointStateMachine->input(data, rawInput, cs);
		if (m_pointStateMachine->done())
		{
			auto center = m_arc->center();
			double radius = calRadius(center, m_pointStateMachine->getPoint());
			m_arc->set(center, radius, m_arc->startAngle(), m_arc->endAngle());
			drawFinish(scene);
			emit finished();
			return;
		}
		else if(cs == CS_MOUSEMOVE)
		{
			if (data.type() == QVariant::Vector3D)
			{
				auto pt = data.value<QVector3D>();
				osg::Vec3d point = { pt.x(), pt.y(), pt.z() };
				set3DRubberLineP2(point);
				auto center = m_arc->center();
				double radius = calRadius(center, point);
				m_arc->set(center, radius, m_arc->startAngle(), m_arc->endAngle());
			}
		}
		else 
		{
			if (data.type() == QVariant::Double)
			{
				double radius = data.value<double>();
				if (radius <= 0.0)
				{
					remark(tr("圆的半径必须不小于0"));
				}
				m_arc->set(m_arc->center(), radius, m_arc->startAngle(), m_arc->endAngle());
				drawFinish(scene);
				emit finished();
			}
		}
		return;
	}	
}

void Radius3DHandler::drawFinish(Scene * scene)
{
	auto undoStack = scene->undoStack();
	std::vector<std::shared_ptr<Ent>> origins;
	origins.push_back(m_originArc);
	std::vector<std::shared_ptr<Ent>> results;
	results.push_back(m_arc);
	undoStack->push(new OpReplace(origins, results));
}

double Radius3DHandler::calRadius(const osg::Vec3d& centerOCS, const osg::Vec3d& ptWCS)
{
	auto m = m_arc->getMatrix();
	auto v = ptWCS - centerOCS * m;
	auto vNormalLen = v * m_arc->zAxis();
	auto vNormal = m_arc->zAxis() * vNormalLen;
	auto vPlane = v - vNormal;
	auto radius = vPlane.length();
	return radius;
}




